VO(globa) === global
function fun3() {
  console.log(3)
}

function fun2() {
  console.log(2)
  fun3()
  console.log(4)
}

function fun1(x) {
  console.log(1)
  var a = 'hello'
  var b = function privateB() {}
  function c() {}
  fun2()
  console.log(5)
}
fun1(22) // 1 2 3 4 5  压栈，出栈，先进后出原则


// 执行栈
1 首先程序会创建 全局执行上下文 GO（globalContext）

2 每执行一个函数会创建一个可执行上下文 EC（execution context）
  一个函数 创建一个 EC，EC就是整个函数的执行环境

3 执行全局代码 创建全局执行上下文 压入执行上下文栈 （Execution Context Static 执行栈 简称 ECS）
ECStatic = [
  globalContext
]

4 全局执行上下文初始化 
ECStatic = [
  fun3,
  fun2,
  fun1ExecutionContext = {
    // 活动对象 Activation object
    AO = {
      argumens: {
        0: 22,
        length: 1
      },
      x: 22,
      c: pointer to function c(),
      a: undefined, // 创建阶段是 undefined ，执行阶段是 hello
      b: undefined // 创建阶段是 undefined ，执行阶段是 privateB
    },
    // 作用域链
    scopeChain: [AO.globalContext.VO],
    // this 此时还没有this，调用的时候才能确定 this
    this: undefined
  },
  // 全局执行上下文
  globalContext = {
    // 变量对象 Variable object 
    VO: [global], 
    // 作用域
    scope: [globalContext.VO], 
    // this 全局时，指向 globalContext.VO
    this: globalContext.VO 
  }
]

5 变量对象VO：执行上下文的特殊对象，存储上下文的函数声明，函数形参和变量
VO{
  变量声明,
  函数声明,
  函数形参
}

6 活动对象AO：在函数执行上下文中，变量对象（VO）被表示为活动对象（AO） (动态创建出来的,执行函数的时候创建)
AO{
  内部的arguments,
  内部定义的函数(函数声明，表达式不行),
  绑定上下文的环境变量,
  内部定义的变量
}

  AO创建全过程：
  1 创建AO
  2 根据参数把AO赋值
  3 作用域链this给值
  4 执行函数上下文
  5 执行函数
  6 压栈
  7 弹栈 （闭包不会弹栈）

  AO对象分为两个阶段: (以函数fun1 的 a b 变量 为例)
  1) 创建阶段 -> 变量提升都是在这个阶段完成的
    AO: {
      a: undefined,
      b: undefined
    }
  2) 执行阶段
    按照函数执行上下文进行执行
    AO: {
      a: 'hello',
      b: pointer to function privateB()
    }
  总结: VO就是函数上下文的连接，AO是函数自带的

// 变量对象(VO)的执行上下文 等于 活动对象(AO)
VO(globalContext) === AO

// globalContext一直处于栈底，无法回收，所以js中挂在window上的内容一直无法回收

7 总结：js同步执行栈，异步执行队列；队列是有优先级的；队列的特点是先进先出，栈的特点是先进后出:
  队列又分为宏队列(macro queue)和微队列(micro queue)，微队列执行优先级高于宏队列
  宏队列：script（全局任务）, setTimeout, setInterval, setImmediate, ajax, 点击事件 等
  微队列：process.nextTick, Promise, Object.observer, MutationObserver 等


// demo如下：
var a = 10;
function test(x) {
  var b = 20;
}
test(30)

VO(globalContext) = {
  a: 10,
  test: <reference to function>
}

VO(test functionCOntext) = {
  x: 30,
  b: 20
}

function test1(a, b) {
  var c = 10
  function d() {}
  (function x() {})
}
test1(10)

AO(test1) = {
  a: 10,
  b: undefined,
  c: 10,
  d: <reference to function>
}
注意这里的AO没有 x，因为 x 是一个函数表达式，并不是函数声明